import os
import time
import hmac
import hashlib
import base64
import requests
from urllib.parse import urlencode
import pytest

# 腾讯云API配置
SECRET_ID = "AKIDEXAMPLE"  # 替换为实际SecretId
SECRET_KEY = "SECRETKEYEXAMPLE"  # 替换为实际SecretKey
ENDPOINT = "cvm.tencentcloudapi.com"
SERVICE = "cvm"
VERSION = "2017-03-12"

# 签名生成函数（修正版）
def generate_signature(secret_key, params):
    """修正后的V3签名生成方法"""
    params = {k: v for k, v in params.items() if v is not None}  # 过滤空值参数
    sorted_params = sorted(params.items(), key=lambda x: x[0])

    # 构建规范请求串
    canonical_uri = f'/{SERVICE}'
    canonical_query = urlencode(sorted_params)
    http_request_method = "GET"

    # 构建签名原文串
    string_to_sign = (
            f"{http_request_method}\n"
            f"{canonical_uri}\n"
            f"{canonical_query}\n"
            "host=" + ENDPOINT + "\n"
    )

    # HMAC-SHA256签名
    signature = hmac.new(
        secret_key.encode('utf-8'),
        string_to_sign.encode('utf-8'),
        hashlib.sha256
    ).digest()
    return base64.b64encode(signature).decode('utf-8')

# 测试数据修正（添加完整参数）
TEST_CASES = [
    {
        "name": "基础询价",
        "params": {
            "Action": "InquiryPriceRunInstances",
            "Version": VERSION,
            "ImageId": "img-pmqg1cw7",
            "InstanceType": "S5.SMALL1",
            "Placement": {"Zone": "ap-shanghai-2"},
            "SystemDisk": {"DiskSize": 50, "DiskType": "CLOUD_PREMIUM"},
            "InstanceCount": 1
        },
        "expected_code": 200
    },
    {
        "name": "无效镜像ID",
        "params": {
            "Action": "InquiryPriceRunInstances",
            "Version": VERSION,
            "ImageId": "invalid-img-id",
            "Placement": {"Zone": "ap-shanghai-2"}
        },
        "expected_code": 400,
        "expected_error": "InvalidImageId.NotFound"
    }
]

# 修正后的Fixture
@pytest.fixture(scope="module")
def api_config():
    return {
        "url": f"https://{ENDPOINT}",
        "headers": {
            "Content-Type": "application/json",
            "Host": ENDPOINT
        }
    }

# 修正后的测试用例
@pytest.mark.parametrize("test_case", TEST_CASES, ids=lambda x: x["name"])
def test_api_requests(api_config, test_case, mocker):
    # 生成完整参数
    params = {
        "Nonce": int(time.time() * 1000),
        "Timestamp": int(time.time()),
        "SecretId": SECRET_ID,
        "SignatureMethod": "TC3-HMAC-SHA256",  # 修正签名方法
        "SignatureVersion": "2"
    }

    # 生成V3签名
    params["Signature"] = generate_signature(SECRET_KEY, params)

    # 模拟请求
    mock_response = mocker.patch("requests.get")
    mock_response.return_value.status_code = test_case["expected_code"]

    if test_case["expected_code"] == 200:
        mock_response.return_value.json.return_value = {
            "Response": {
                "Price": {"TotalCost": "0.00000000"},
                "RequestId": "TEST-REQUEST-ID"
            }
        }
    else:
        mock_response.return_value.json.return_value = {
            "Response": {
                "Error": {
                    "Code": test_case.get("expected_error", "UnknownError"),
                    "Message": "Simulated error"
                }
            }
        }

    # 执行请求
    response = requests.get(
        api_config["url"],
        params=params,
        headers=api_config["headers"]
    )

    # 断言修正
    assert response.status_code == test_case["expected_code"]
    if test_case["expected_code"] == 200:
        assert "Price" in response.json()["Response"]
    else:
        assert test_case.get("expected_error") in response.json()["Response"]["Error"]["Code"]

# ----------------------------
# 新增：启动命令入口
# ----------------------------
if __name__ == "__main__":
    pytest.main([
        "-s",               # 显示详细日志
        "-v",               # 详细模式
        "--html=report.html",  # 生成HTML报告
        "--self-contained-html"  # 将CSS嵌入HTML
    ])